package cn.com.cym.gamezao.web;

import cn.com.cym.gamezao.annotation.AuthToken;
import cn.com.cym.gamezao.annotation.CommonApi;
import cn.com.cym.gamezao.base.ResultResponse;
import cn.com.cym.gamezao.base.SearchPage;
import cn.com.cym.gamezao.dto.LocalFileDto;
import cn.com.cym.gamezao.entity.LocalFile;
import cn.com.cym.gamezao.entity.authorize.User;
import cn.com.cym.gamezao.exception.BaseException;
import cn.com.cym.gamezao.jwt.JwtUtils;
import cn.com.cym.gamezao.jwt.RequestUser;
import cn.com.cym.gamezao.service.LocalFileService;
import cn.com.cym.gamezao.util.CommonUtils;
import com.auth0.jwt.JWT;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.core.io.InputStreamResource;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.UUID;

@Api(tags = "x-文件管理")
@RestController
@RequestMapping(value = "file")
@CommonApi
@AuthToken(rule = "common.localFile")
public class LocalFileController {
    final LocalFileService thisService;

    public LocalFileController(LocalFileService thisService){
        this.thisService=thisService;
    }

    @ApiImplicitParam(name = "file", value = "file", required = true,dataType = "MultipartFile")
    @ApiOperation(value = "保存文件！")
    @ApiOperationSupport(order = 1, author = "mr.chen")
    @GetMapping("self/{uuid}")
    @AuthToken(rule = "search")
    public ResponseEntity<?> getByUuid(@PathVariable String uuid){
        LocalFile byUuidName = this.thisService.getByUuidName(uuid);
        LocalFileDto dto = new LocalFileDto();
        BeanUtils.copyProperties(byUuidName,dto);
        return ResponseEntity.ok(dto);
    }


    @ApiImplicitParam(name = "file", value = "file", required = true,dataType = "MultipartFile")
    @ApiOperation(value = "保存文件！")
    @ApiOperationSupport(order = 1, author = "mr.chen")
    @PostMapping()
    @AuthToken(rule = "save")
    public ResponseEntity<?> save(@RequestBody MultipartFile file){
        return ResponseEntity.ok(saveFile(file, thisService));
    }


    /**
     * produces 中添加媒体类型是为了在前端显示时不是显示乱码，显示原有格式文件
     * @param uuid uuid
     * @return r
     * @throws FileNotFoundException f
     */
    @ApiImplicitParam(name = "uuid", value = "uuid", required = true,dataType = "String")
    @ApiOperation(value = "下载文件！")
    @ApiOperationSupport(order = 1, author = "mr.chen")
    @GetMapping(value = "/{uuid}",produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE,MediaType.IMAGE_PNG_VALUE,MediaType.APPLICATION_PDF_VALUE,MediaType.IMAGE_JPEG_VALUE,MediaType.IMAGE_GIF_VALUE})
    // @AuthToken(rule = "downLoad")
    public ResponseEntity<?> downLoad(@PathVariable("uuid") @NonNull String uuid) throws FileNotFoundException {

        final LocalFile byUUID = this.thisService.getByUuidName(uuid);
        // 判断是否在白名单里面
        if(!this.thisService.isWhite(uuid)){
            throw new BaseException("该文件无法下载",new ResultResponse("该文件无法下载",HttpStatus.BAD_REQUEST.value()));
        }
        if(byUUID == null){
            throw new BaseException("数据不存在",new ResultResponse("数据不存在",HttpStatus.BAD_REQUEST.value()));
        }

        InputStream inputStream = new FileInputStream(new File(CommonUtils.filePath(uuid+"."+byUUID.getSuffix())));

        InputStreamResource inputStreamResource =new InputStreamResource(inputStream);

        HttpHeaders headers=new HttpHeaders();
        return new ResponseEntity<>(inputStreamResource,headers, HttpStatus.OK);
    }

    /**
     * produces 中添加媒体类型是为了在前端显示时不是显示乱码，显示原有格式文件
     * @param uuid uuid
     * @return r
     * @throws FileNotFoundException f
     */
    @ApiImplicitParam(name = "uuid", value = "uuid", required = true,dataType = "String")
    @ApiOperation(value = "授权下载文件！")
    @ApiOperationSupport(order = 1, author = "mr.chen")
    @GetMapping(value = "/user/{uuid}",produces = {MediaType.APPLICATION_OCTET_STREAM_VALUE,MediaType.IMAGE_PNG_VALUE,MediaType.APPLICATION_PDF_VALUE,MediaType.IMAGE_JPEG_VALUE,MediaType.IMAGE_GIF_VALUE})
    public ResponseEntity<?> downLoadAuthFile(@PathVariable("uuid") String uuid, HttpServletRequest request) throws FileNotFoundException {

        String value = request.getParameter("token");
        System.out.println(value);
        if(!(CommonUtils.isNotEmpty(value) && !JwtUtils.expire(value))){
            throw new BaseException("用户无下载权限",new ResultResponse("用户无下载权限",HttpStatus.BAD_REQUEST.value()));
        }
        // 判断是否过期
        final LocalFile byUUID = this.thisService.getByUuidName(uuid);

        if(byUUID == null){
            throw new BaseException("数据不存在",new ResultResponse("数据不存在",HttpStatus.BAD_REQUEST.value()));
        }

        InputStream inputStream = new FileInputStream(new File(CommonUtils.filePath(uuid+"."+byUUID.getSuffix())));

        InputStreamResource inputStreamResource =new InputStreamResource(inputStream);

        HttpHeaders headers=new HttpHeaders();
        return new ResponseEntity<>(inputStreamResource,headers, HttpStatus.OK);
    }

    @ApiImplicitParam(name = "fileName", value = "fileName", required = true,dataType = "String")
    @ApiOperation(value = "下载文件！")
    @ApiOperationSupport(order = 1, author = "mr.chen")
    //@AuthToken(rule = "downLoad")
    @GetMapping("/auth/{fileName}")
    public ResponseEntity<?> downLoadFile(@PathVariable("fileName") @NonNull String fileName) throws FileNotFoundException {

        InputStream inputStream = new FileInputStream(CommonUtils.filePath(fileName));

        InputStreamResource inputStreamResource =new InputStreamResource(inputStream);

        HttpHeaders headers=new HttpHeaders();

        return new ResponseEntity<>(inputStreamResource,headers, HttpStatus.OK);
    }


    @ApiImplicitParam(name = "searchPage", value = "searchPage", required = true,dataType = "SearchPage")
    @ApiOperation(value = "分页显示page！")
    @ApiOperationSupport(order = 4, author = "mr.chen")
    @PostMapping("/page")
    @AuthToken(rule = "page")
    public ResponseEntity<?> page(@RequestBody SearchPage searchPage){
        Page<?> byPageable = this.thisService.findByPageable(searchPage);
        return ResponseEntity.ok(byPageable);
    }

    @ApiImplicitParam(name = "uuid", value = "uuid",paramType = "path", required = true,dataType = "SearchPage")
    @ApiOperation(value = "删除附件！")
    @ApiOperationSupport(order = 4, author = "mr.chen")
    @DeleteMapping("/{uuid}")
    @AuthToken(rule = "delete")
    public ResponseEntity<?> deleteFile(@PathVariable String uuid){
        final LocalFile byUuidName = this.thisService.getByUuidName(uuid);
        File file = new File(CommonUtils.filePath(uuid+"."+byUuidName.getSuffix()));
        if(file.exists()){
            file.delete();
            thisService.deleteById(byUuidName.getId());
        }
        return ResponseEntity.ok(new ResultResponse("删除成功",HttpStatus.OK.value()));
    }

    public static LocalFile saveFile(MultipartFile file, LocalFileService thisService) {
        LocalFile localFile=new LocalFile();
        localFile.setFileSize(file.getSize());
        String originalFilename = file.getOriginalFilename();
        localFile.setRealName(originalFilename);
        localFile.setUuidName(UUID.randomUUID().toString());
        String[] strArray = originalFilename.split("\\.");
        int suffixIndex = strArray.length -1;
        localFile.setSuffix(strArray[suffixIndex]);
        CommonUtils.saveFile(localFile,file);
        thisService.save(localFile);
        return localFile;
    }
}
